﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Collections;
using System.Collections.Generic;
using Microsoft.SharePoint.Utilities;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.Office.Server;
using Microsoft.SharePoint.WebControls;
using System.Text;
using System.IO;
using System.Net;
namespace Microsoft.MCSUK.SPSiteDirectory2010
{
    public class GlobalMethods
    {
        public void DeactivateFeatureInWebApp(SPWebApplication webApplication, Guid featureID)
        {
            try
            {
                if (webApplication != null) //if a valid web application has been passed in
                {
                    SPFeature feature = webApplication.Features[featureID];
                    if (feature != null)
                    {
                        webApplication.Features.Remove(featureID, true);
                    }
                }
                else //if there is no web application passed in, we scan all web applications and deactivate all instances of the feature
                {
                    foreach (SPWebApplication webApp in SPWebService.ContentService.WebApplications)
                    {
                        SPFeature feature = webApp.Features[featureID];
                        if (feature != null)
                        {
                            webApplication.Features.Remove(featureID, true);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
        }
        public Guid ReActivateFeatureInWebApp(SPWebApplication webApplication, Guid featureID, string jobName, SPSchedule schedule)
        {
            Guid jobID = new Guid();
            try
            {
                DeactivateFeatureInWebApp(webApplication, featureID);//deactivate the feature first
                DeleteJob(webApplication, jobName);//delete the job
                webApplication.Features.Add(featureID, true);//activate the feature
                if (jobName == GlobalConstants.ScanJobName)//add the schedule
                {
                    ScanJob scanJob = new ScanJob(webApplication);
                    scanJob.Schedule = schedule;
                    scanJob.Update();
                    jobID = scanJob.Id;
                }
                else if (jobName == GlobalConstants.DeleteBrokenListingJobName)
                {
                    DeleteBrokenListingJob deleteBrokenListingJob = new DeleteBrokenListingJob(webApplication);
                    deleteBrokenListingJob.Schedule = schedule;
                    deleteBrokenListingJob.Update();
                    jobID = deleteBrokenListingJob.Id;
                }
            }
            catch (Exception ex)
            {
                this.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return jobID;
        }
        public void DeleteJob(SPWebApplication webApplication, string jobName)
        {
            try
            {
                foreach (SPJobDefinition job in webApplication.JobDefinitions)
                {
                    if (job.Name == jobName)
                        job.Delete();
                }
            }
            catch (Exception ex)
            {
                this.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
        }
        public void WriteULSEntry(Exception ex, TraceSeverity tSev, string message)
        {
            SPDiagnosticsCategory category = new SPDiagnosticsCategory(GlobalConstants.ULSCategoryName, TraceSeverity.Verbose, EventSeverity.Verbose);
            if (string.IsNullOrEmpty(message))
            {
                SPDiagnosticsService.Local.WriteTrace(100, category, tSev, string.Concat(ex.ToString(), ex.StackTrace), null);
            }
            if (ex != null)
            {
                SPDiagnosticsService.Local.WriteTrace(100, category, tSev, message, null);
            }
        }
        public string GetSiteListingsListURL(SPWeb siteDirectoryWeb)
        {
            string siteListingsListURL = "";
            try
            {
                siteListingsListURL = string.Concat(siteDirectoryWeb.ServerRelativeUrl, GlobalConstants.SiteRelativeSiteListingsListURL);
                if (siteListingsListURL.StartsWith("//")) // necesary for if the siteDirectoryWeb is the root of a web application
                {
                    siteListingsListURL = siteListingsListURL.Remove(0, 1);
                }
            }
            catch (Exception ex)
            {
                WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return siteListingsListURL;
        }

        public void DeleteSiteListingItem(SPList siteListingsList, int listItemID)
        {
            try
            {
                SPListItem tempSiteListing = siteListingsList.Items.GetItemById(listItemID);
                tempSiteListing.Recycle();
            }
            catch (Exception ex)
            {
                this.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
        }
        public void LockUpdateListItem(SPList siteListingsList, int listItemID, Hashtable fieldsToUpdate)
        {
            try
            {
                try
                {
                    //attempt the update initially
                    AttemptUpdateListItem(siteListingsList, listItemID, fieldsToUpdate);
                }
                catch
                {
                    //catch the exception and try again. If an exception is raised it is likely that there was a save conflict with the other timer job. If the second update fails, move on and try again next time the job runs
                    AttemptUpdateListItem(siteListingsList, listItemID, fieldsToUpdate);
                }
            }
            catch (Exception ex)
            {
                this.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
        }
        private static void AttemptUpdateListItem(SPList siteListingsList, int listItemID, Hashtable fieldsToUpdate)
        {
            SPListItem tempSiteListing = siteListingsList.Items.GetItemById(listItemID);
            foreach (DictionaryEntry field in fieldsToUpdate) //add the value to the list item
            {
                if ((tempSiteListing.Fields.ContainsField(field.Key.ToString())) && (field.Value != null)) //check that the field exists. administrators may have manually removed the field after the solution was deployed
                {
                    tempSiteListing[field.Key.ToString()] = field.Value;
                }
            }
            tempSiteListing.SystemUpdate(false); //update the list item
        }
        public string GetPresenceHTMLFromUVC(SPSite thisSite, SPFieldUserValueCollection uvc)
        {
            StringBuilder html = new StringBuilder("");
            try
            {
                SPWeb thisWeb = thisSite.RootWeb; // do not need to dispose of rootweb
                foreach (SPFieldUserValue uv in uvc)
                {
                    string sipAddress = "";
                    //Get the sip address if it exists
                    SPListItem user = thisWeb.SiteUserInfoList.GetItemById(uv.LookupId);
                    if (user["SipAddress"] != null)
                    {
                        sipAddress = user["SipAddress"].ToString();
                    }
                    //construct the html for this user and add to overall html
                    html.Append(String.Concat(
                    "<div id\"PresenceLink"
                    , sipAddress
                    , "\">"
                    , "<img border=\"0\" height=\"12\" src=\"/_layouts/images/imnhdr.gif\" onload=\"IMNRC('"
                    , sipAddress
                    , "')\" ShowOfflinePawn=\"1\" style=\"padding-right: 3px;\" id=\"PresencePawn"
                    , sipAddress
                    , "\" alt=\"presence pawn for "
                    , sipAddress
                    , "\"/>"
                    , "<a href=\""
                    , thisWeb.Url
                    , "/_layouts/userdisp.aspx?ID="
                    , uv.LookupId
                    , "\" id=\"ProfileLink"
                    , sipAddress
                    , "\">"
                    , uv.User.Name
                    , "</a></div>"
                    ));
                }
                
            }
            catch (Exception ex)
            {
                this.WriteULSEntry(ex, TraceSeverity.Unexpected, null);
            }
            return html.ToString();
        }
        public Boolean DoesSiteExist(string siteURL)
        {
            Boolean exists = false;
            if (!string.IsNullOrEmpty(siteURL)) //is the URL is empty, assume the site does not exist
            {
                try
                {
                    SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        using (SPSite site = new SPSite(siteURL)) //used because SPSite.Exists has issues in timer jobs. This will throw a FileNotFoundException exception if the site collection is not valid
                        {
                            using (SPWeb web = site.OpenWeb()) //OpenWeb without a parameter opens the lowest web in the SPSite's URL
                            {
                                bool allowUnsafeUpdates = web.AllowUnsafeUpdates;
                                web.AllowUnsafeUpdates = true;
                                try
                                {
                                    if (web.Url.TrimEnd('/') == siteURL.TrimEnd('/')) //Need to check this is the right web because if the web we are looking for does not exist, this will return its parent web
                                    {
                                        string webTitle = web.Title; //this will throw a FileNotFoundException if the web is not valid.
                                        exists = true;
                                    }
                                    else
                                    {
                                        exists = false;
                                    }
                                }
                                finally
                                {
                                    web.AllowUnsafeUpdates = allowUnsafeUpdates;
                                }
                            }
                        }
                    });
                }
                catch (FileNotFoundException) //if it is not an existing sharepoint site, check to see if it is an external site
                {
                    try
                    {
                        WebRequest req = WebRequest.Create(siteURL);
                        req.Timeout = 15000;
                        WebResponse res = req.GetResponse();
                        exists = true; //if the web response does not throw an exception, we can assume that the site exists
                    }
                    catch (WebException)
                    {
                        exists = false; //if the web response does throw an exception which contains 404, the site does not exist
                    }
                }
            }
            return exists;
        }
    }
}

